package com.mantou.mantouaiagent.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.crypto.SecureUtil;
import com.mantou.mantouaiagent.resp.ResultData;
import com.mantou.mantouaiagent.resp.ReturnCodeEnum;
import com.mantou.mantouaiagent.util.IpUtil;
import com.mantou.mantouaiagent.util.MinIoUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * 登录验证码
 *
 * @auther zzyy
 * @create 2024-11-11 18:51
 */
@RestController
public class CaptchaController
{
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    private MinIoUtil minIoUtil;
    @Resource
    private RedisTemplate<String,String> stringRedisTemplate;
    @GetMapping(value = "/captcha/create")
    public ResultData createCaptcha(HttpServletRequest request) throws IOException
    {
        String url = "";
        //1 糊涂工具包定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(120, 40);
        String ipAddress = IpUtil.getIpAddress(request);
        //2 上传到minio服务器的文件名  使用浏览器的ip地址作为文件名 来保证每次生成验证码的唯一性
        //这里不用uuid的原因 安全加固保密性 防止用户连续点击多次生成验证码导致内存爆满
        String fileName = "captcha-" + SecureUtil.md5(ipAddress);
        log.info("=====fileName: {}, lineCaptchaCode: {}", fileName,lineCaptcha.getCode());
        //3 读取验证码的流式对象
        InputStream inputStream = null;

        try
        {
            //思考 这里是否需要保证原子性 实现原子性的方式有哪些？1.lua脚本 2.分布式锁 3.阻塞获取锁
            inputStream = new ByteArrayInputStream(lineCaptcha.getImageBytes());
            url = minIoUtil.upload(fileName, inputStream, "image/png");
            // 验证码存储到 Redis,前面的fileName变量就是存入redis的key
            stringRedisTemplate.opsForValue().set(fileName, lineCaptcha.getCode(),60, TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultData.fail(ReturnCodeEnum.RC999.getCode(),
                    ReturnCodeEnum.RC999.getMessage() + " " + e.getMessage());
        } finally {
            inputStream.close();
        }

        return ResultData.success(url);
    }

    // 添加这个新的代理接口
    @GetMapping("/captcha/image")
    public ResponseEntity<byte[]> getCaptchaImage(@RequestParam String url) {
        try {
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<byte[]> imageResponse = restTemplate.getForEntity(url, byte[].class);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);
            headers.setCacheControl("no-cache");

            return new ResponseEntity<>(imageResponse.getBody(), headers, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
}
